<?php

declare(strict_types=1);

namespace app\admin\controller;

use app\admin\BaseXpController;
use think\facade\View;
use think\facade\Request;
use app\admin\model\Error;
use app\admin\model\Admin;
use think\facade\Cookie;
use app\system\model\LogLogin as Log;
use app\admin\middleware\Auth;
use RobThree\Auth\TwoFactorAuth;
use RobThree\Auth\Providers\Qr\BaconQrCodeProvider;
use think\facade\Config;

class Index extends BaseXpController
{

    /**
     * 二步验证 error key
     * @var string
     */
    private $totp = 'totp';

    /**
     * 登录 error key
     * @var string
     */
    private $login = 'login';

    /**
     * 登录页面
     */
    public function index()
    {
        View::assign('year', date('Y'));
        // 判断是否登录
        $auth = new Auth;
        // 已登录 ? 跳转到后台首页 : 否则跳转到登录页
        View::assign('version', Config::get('xpversion.version'));
        return $auth->check() ? redirect(url('admin/dashboard/index')->build()) : View::fetch();
    }

    /**
     * 登录验证成功后二步验证解锁验证操作
     * @param Admin $admin 管理员信息
     */
    private function saveTotp($admin)
    {
        $check = Error::check($this->totp);
        $error = '';
        if ($check) {
            $error = '操作过于频繁，请明天再试';
        } else {
            $code = input('post.code');
            if (empty($code)) {
                $error = '请输入验证码';
            } else {
                $tfa = new TwoFactorAuth(new BaconQrCodeProvider());
                $result = $tfa->verifyCode($admin->totp, $code);
                if ($result) {
                    // 验证成功, 设定Cookie
                    $md5 = md5($admin->totp . $admin->salt);
                    Cookie::set('totp', $this->encrypt($md5), 0);
                    Log::add($admin->username, '解锁成功');
                    Error::clear($this->totp);
                } else {
                    Error::add($this->totp);
                    $error = '验证码验证失败';
                }
            }
        }
        if ($error) {
            return json(['msg' => $error]);
        }
        return json(['code' => '200']);
    }

    /**
     * 二步验证解锁页面
     */
    public function lock()
    {
        $auth = new Auth;
        $admin = $auth->check();
        $isAjax = Request::isAjax();
        $response = null;
        if (!$admin) {
            // 未登录
            Error::add($this->totp);
            $response = $isAjax ? json(['msg' => '请先登录']) : redirect(url('admin/index/index')->build());
        } else {
            // 未开启二步验证
            if (empty($admin->totp)) {
                $response = $isAjax ? json(['msg' => '请先开启二步验证']) : redirect(url('admin/dashboard/index')->build());
            }
        }
        if ($isAjax) {
            $response = $this->saveTotp($admin);
        }
        return $response ? $response : View::fetch();
    }

    /**
     * 登录成功
     * @param Admin $admin 管理员信息
     */
    private function loginSuccess($admin)
    {
        if ($admin->login != 0) {
            return json(['msg' => '账号无权登录']);
        }
        if ($admin->status != 0) {
            return json(['msg' => '账号已停用']);
        }
        $rememberme = input('post.rememberme', 'off');
        // 登录成功
        $salt = generateSalt();
        $ip = Request::ip();
        $admin->update_time = time();
        $admin->update_ip = $ip;
        $admin->salt = $salt;
        $admin->save();
        Log::add($admin->nickname, '登录成功');
        // 设置 Cookies
        $encryptedPassword = crypt($admin->password, $this->xpConfig['password_salt'] . $salt);
        $expire = $rememberme == 'on' ? 3600 * 24 * 365 : 0; // 365天
        $auth = $admin->id . "\t" . $ip . "\t" . $encryptedPassword . "\t" . time();
        Cookie::set('auth', $this->encrypt($auth), $expire);
        // 清除错误次数
        Error::clear($this->login);
        Error::clear('request');
        return json(['code' => '200']);
    }

    /**
     * 登录操作
     */
    public function login()
    {
        $captcha = input('post.captcha');
        $username = input('post.username');
        $password = input('post.password');
        if (!captcha_check($captcha)) {
            // 验证失败
            Log::add($username, '验证码错误');
            Error::add($this->login);
            $error = '请输入正确的验证码';
        } else {
            // 1. 检查错误次数
            $check = Error::check($this->login);
            if ($check) {
                $error = '操作过于频繁，请明天再试';
            } else {
                // 2. 检查账户
                $admin = Admin::where('username', '=', $username)->find();
                if ($admin) {
                    if (password_verify($password, $admin->password)) {
                        return $this->loginSuccess($admin);
                    } else {
                        Log::add($username, '密码输入错误');
                    }
                }
                Log::add($username, '账号不存在');
                Error::add($this->login);
                $error = '用户或密码错误';
            }
        }
        return json(['msg' => $error]);
    }
}
